package com.dylan.历史.java8.StreamAPI;

import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by Dylan on 2018/7/23.
 */
public class Stream处理5_map和分组 {

    public static void main(String[] args) {
        // 收集到Map
        Map<Long, String> map1 = getPerson().collect(Collectors.toMap(Person::getId, Person::getName));
        Map<Long, Person> map2 = getPerson().collect(Collectors.toMap(Person::getId, x -> x));
        Map<Long, Person> map3 = getPerson().collect(Collectors.toMap(Person::getId, Function.identity()));

        // 收集到Map,当多个值对应到同一个键时,需要指定需要保留的值
        Map<Integer, String> map4 = getWords().collect(Collectors.toMap(String::length, Function.identity(), (existingValue, newValue) -> existingValue));

        // 收集到Map,value是一个集合
        Map<Integer, Set<String>> map5 = getWords().collect(Collectors.toMap(String::length, Collections::singleton, (a, b) -> {
            Set<String> r = new HashSet<>(a);
            r.addAll(b);
            return r;
        }));
        TreeMap<Integer, Set<String>> map6 = getWords().collect(Collectors.toMap(String::length, Collections::singleton, (a, b) -> {
            Set<String> r = new HashSet<>(a);
            r.addAll(b);
            return r;
        }, TreeMap::new));

        // 根据字符串长度进行分组统计
        Map<Integer, List<String>> map7 = getWords().collect(Collectors.groupingBy(String::length));

        // 根据字符串长度进行分组统计,结果收集到Set中
        Map<Integer, Set<String>> map8 = getWords().collect(Collectors.groupingBy(String::length, Collectors.toSet()));

        // 统计不同长度的字符串数量
        Map<Integer, Long> map9 = getWords().collect(Collectors.groupingBy(String::length, Collectors.counting()));

        // 根据字符串长度进行分组,然后每组中取首字母最小的字符串
        Map<Integer, Optional<String>> map10 = getWords().collect(Collectors.groupingBy(String::length, Collectors.minBy(Comparator.comparing(s -> s.charAt(0)))));

        // 根据字符串长度进行分组,然后每组中取最大的首字母.其中mapping()方法中的第一个参数必须指定类型(或者使用静态方法引用 String::length),否则无法编译通过
        Map<Integer, Optional<Character>> map11 = getWords().collect(Collectors.groupingBy(String::length, Collectors.mapping((String s) -> s.charAt(0), Collectors.maxBy(Comparator.comparing(Function.identity())))));

        // 根据字符串长度进行分组,然后取每组中的首字母集合
        Map<Integer, Set<Character>> map12 = getWords().collect(Collectors.groupingBy(String::length, Collectors.mapping(s -> s.charAt(0), Collectors.toSet())));

        // 根据字符串的首字母进行分组,对每组的字符串长度进行统计(最大值,最小值,求和)
        Map<Character,IntSummaryStatistics> map13 = getWords().collect(Collectors.groupingBy(s -> s.charAt(0), Collectors.summarizingInt(String::length)));

        // 根据字符串长度进行分组,然后将每组中的字符串进行连接
        Map<Integer, String> map14 = getWords().collect(Collectors.groupingBy(String::length, Collectors.reducing("", Function.identity(), (s, t) -> s.length() ==0 ? t : s + "," + t)));
        for (Map.Entry<Integer, String> entry : map14.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }

        // 根据字符串长度进行分组,然后将每组中的字符串进行连接
        Map<Integer, String> map15 = getWords().collect(Collectors.groupingBy(String::length, Collectors.mapping(Function.identity(), Collectors.joining(","))));
    }

    private static Stream<String> getWords() {
        return Pattern.compile("[\\P{L}]+").splitAsStream("Ramesses VI was the fifth ruler of the Twentieth Dynasty of Egypt. He succeeded Ramesses V and reigned for about eight years in the mid-to-late 12th century BC before dying in his forties. Egypt lost control of its last strongholds in Canaan around the time of his reign. The pharaoh's power waned in Upper Egypt during his rule, while the high priest of Amun, Ramessesnakht, was turning Thebes in Upper Egypt into the religious capital and a second center of power on par with Pi-Ramesses in Lower Egypt, where the pharaoh resided. He was fond of cult statues of himself; more are known to portray him than any other Twentieth-Dynasty king after his father, Ramesses III. He usurped KV9, a tomb in the Valley of the Kings planned by and for Ramesses V, and had it enlarged and redecorated for himself. His mummy lay untouched for fewer than 20 years before pillagers damaged it.");
    }

    private static Stream<Person> getPerson() {
        return Stream.iterate(0, x -> x + 1).map(Integer::longValue).map((x) -> new Person(x, "姓名" + x)).limit(10);
    }

    static class Person {
        private Long id;
        private String name;

        public Person(Long id, String name) {
            this.id = id;
            this.name = name;
        }

        public Long getId() {
            return id;
        }

        public String getName() {
            return name;
        }
    }
}
